﻿using System;
using System.IO;
using System.Linq;

namespace CSharpExecutor
{
	public class Program
	{
		#region Constants

		private const string FLAG_USAGE = "-h";

		#endregion

		#region Methods

		public static void Main(string[] args)
		{
#if DEBUG
			args = new string[] { "test.csharp", "Test.Program.Main" };
#endif

			log4net.Config.XmlConfigurator.Configure();

			if (CheckForUsage(args))
			{
				return;
			}

			var filename = AcquireFilename(args);

			var fullyQualifiedName = AcquireStartPoint(args);
			var scriptArgs = AcquireScriptArgs(args);

			var result = new Executor(filename).Execute(fullyQualifiedName, scriptArgs);
			if (result != null)
			{
				Console.WriteLine("Result: {0}", result);
			}
		}

		private static bool CheckForUsage(string[] args)
		{
			Require.Variable(() => args).IsNotNull();
			if ((args.Length == 0) || (args[0] == FLAG_USAGE))
			{
				Console.WriteLine("Usage:\n\tcsexec filename.cs [class name.method name]\n\t\tExecute a C# script file.\n\tcsexec -h\n\t\tGet this message.");
				return true;
			}
			return false;
		}

		private static string AcquireFilename(string[] args)
		{
			Require.Variable(() => args).IsNotNull();
			Require.Variable(() => args[0]).IsNotNullOrEmpty();
			if (!File.Exists(args[0]))
			{
				throw new FileNotFoundException("The requested file does not exist.", args[0]);
			}

			return args[0];
		}

		private static string AcquireStartPoint(string[] args)
		{
			Require.Variable(() => args).IsNotNull();
			var fullyQualifiedName = "Program.Main";
			if (args.Length > 1)
			{
				fullyQualifiedName = args[1];
			}
			return fullyQualifiedName;
		}

		private static string[] AcquireScriptArgs(string[] args)
		{
			Require.Variable(() => args).IsNotNull();
			if (args.Length > 2)
			{
				return args.Skip(2).ToArray();
			}
			return new string[0];
		}

		#endregion
	}
}